﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SPSAndong.Comm
{
    public class SocClient
    {
        public Action<string> OnReceiveDate;
        public Action<StateObject> OnReceive;

        private Socket soc = null;

        private int _port;
        public int Port
        {
            get { return _port; }
            private set { _port = value; }
        }

        private IPAddress _ip;
        public IPAddress Ip
        {
            get { return _ip; }
            private set { _ip = value; }
        }

        public SocClient(IPAddress ip, int nPort)
        {
            this.Port = nPort;
            this.Ip = ip;
        }

        /// <summary>
        /// 连接Socket服务端
        /// </summary>
        /// <returns>是否连接成功</returns>
        public bool Connect()
        {
            soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                soc.Connect(new IPEndPoint(Ip, Port));
                return true;
            }
            catch
            {
                return false;
            }
        }

        public void DisConnect()
        {
            if (null != soc)
            {
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
            }
        }

        public string ReceiveData()
        {
            string strData = string.Empty;
            if (null != soc && soc.Connected)
            {
                byte[] bytes = new byte[1024];
                int nLength = soc.Receive(bytes);
                for (int i = 0; i < nLength; i++)
                {
                    strData += bytes[i].ToString("X2"); //十六进制
                    OnReceiveDate?.BeginInvoke(strData,null,null);
                }
            }

            return strData;
        }

        /// <summary>
        /// 十六进制字符串转十六进制字节数组
        /// </summary>
        /// <param name="hexString">十六进制字符串</param>
        /// <returns></returns>
        private byte[] strToToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
            return returnBytes;
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="strData">十六进制字符串</param>
        /// <returns>是否发送成功</returns>
        public bool SendData(string strData)
        {
            byte[] bytes = strToToHexByte(strData);
            try
            {
                soc.Send(bytes);
                return true;
            }
            catch
            {
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
                if (Connect())
                {
                    return SendData(strData);
                }
            }
            return false;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="bytes">十六进制字节</param>
        /// <returns>是否发送成功</returns>
        public bool SendData(byte[] bytes)
        {
            try
            {
                soc.Send(bytes);
                return true;
            }
            catch
            {
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
                if (Connect())
                {
                    return SendData(bytes);
                }
            }
            return false;
        }

        public class StateObject
        {
            // Client socket. 
            public Socket workSocket = null;
            // Size of receive buffer. 
            public const int BufferSize = 256;
            // Receive buffer. 
            public byte[] buffer = new byte[BufferSize];
            // Received data string. 
            public StringBuilder sb = new StringBuilder();
        }
        //public void Receive()
        //{
        //    try
        //    {
        //        // Create the state object. 
        //        StateObject state = new StateObject();
        //        state.workSocket = soc;
        //        // Begin receiving the data from the remote device. 
        //        soc.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
        //        new AsyncCallback(OnReceive), state);
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine(e.ToString());
        //    }
        //}

    }
}
